package com.market.domain;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;

import javax.faces.context.FacesContext;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.primefaces.model.map.DefaultMapModel;
import org.primefaces.model.map.LatLng;
import org.primefaces.model.map.MapModel;
import org.primefaces.model.map.Marker;

@Entity
@Table(name = "location")
public class Location extends BaseObject {

	/**
	 * 
	 */
	private static final long serialVersionUID = 2158645749724881965L;
	
	/**
	 * Use this property to save all users of this location,
	 * For example, when we want to send a message to all users of this location
	 */
	
	@Transient
	private List<User> users = new ArrayList<User>();
	

	public List<User> getUsers() {
		return users;
	}

	public void setUsers(List<User> users) {
		this.users = users;
	}

	/**
	 * Use this for temporarily saving orders when query orders group by
	 * locaion;
	 * 
	 * 
	 */
	@Transient
	private List<Order> orders = new ArrayList<Order>();

	public List<Order> getOrders() {
		return orders;
	}

	public void setOrders(List<Order> orders) {
		this.orders = orders;
	}

	public enum TYPE {
		PUBLIC, PRIVATE;
		private String getMessage(String key) {
			Locale locale = FacesContext.getCurrentInstance().getViewRoot()
					.getLocale();
			java.util.ResourceBundle resBundle = ResourceBundle.getBundle(
					"com.market.messages", locale);
			return resBundle.getString(key);
		}

		public String getLabel() {
			return this.getMessage("LOCATION_TYPE_" + this.toString());
		}

	}

	@Override
	public boolean equalsId(Object o) {
		if ((o instanceof Location) && ((Location) o).getId().equals(id)) {
			return true;
		}
		return false;
	}

	/**
	 * This method return pickup schedule label show in location list, like :
	 * Tuesday, Saturday
	 * 
	 * @return
	 */
	@Transient
	public String getPickupScheduleLabel() {
		String label = "";
		if (this.pickupSchedules != null && this.pickupSchedules.size() > 0) {
			for (PickupSchedule schedule : this.pickupSchedules) {
				if (schedule.getIsAvailable() == Boolean.TRUE) {
					label = label + " " + schedule.getDayOfWeek().getLabel();
				}
			}
		}
		return label;
	}

	/**
	 * This method return all pickup day marked as available.
	 * @return
	 */
	public List<PickupSchedule> getAvailablePickupSchedules() {
		List<PickupSchedule> availablePickupSchedules = new ArrayList<PickupSchedule>();
		for (PickupSchedule schedule : this.pickupSchedules) {
			if (schedule.getIsAvailable()) {
				availablePickupSchedules.add(schedule);
			}
		}
		return availablePickupSchedules;
	}

	@Transient
	private DefaultMapModel map = new DefaultMapModel();

	@Transient
	public MapModel getMap() {
		String locationNote;
		if (this.getLatitude() != null
				&& this.getLatitude().isEmpty() == Boolean.FALSE
				&& this.getLongitude() != null
				&& this.getLongitude().isEmpty() == Boolean.FALSE) {
			locationNote = this.getAddress() + "\n"
					+ this.getMessage("pickUpDateTime") + ":";
			for (PickupSchedule schedule : this.getPickupSchedules()) {
				locationNote = locationNote + "\n"
						+ schedule.getDayOfWeek().getLabel() + " "
						+ schedule.getTimeRangeLabel();
			}

			Marker marker = new Marker(new LatLng(Double.parseDouble(this
					.getLatitude()), Double.parseDouble(this.getLongitude())),
					locationNote);
			marker.setIcon("/resources/images/logo_80_15.png");
			marker.setData(this.getId());
			map.addOverlay(marker);
		}
		return map;
	}

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id = 0L;
	@Column(length = 150)
	private String name;
	@Column(length = 50, nullable = false, unique = true)
	private String number;
	@Column(length = 50)
	private String district;
	@Column(length = 300)
	private String address;
	@Column(length = 15)
	private String postCode;
	@Column(length = 50)
	private String contactPerson;
	@Column(length = 50)
	private String telephone;
	@Column(length = 50)
	private String mobilePhone;
	@Column(length = 50)
	private String email;
	@Column(length = 20)
	@Enumerated(EnumType.STRING)
	private TYPE type = TYPE.PUBLIC;
	@Column(length = 500)
	private String description;
	@Column(columnDefinition = "bit(1) default 0")
	private Boolean isCanceled = Boolean.FALSE;
	@Column(columnDefinition = "bit(1) default 0")
	private Boolean isPrepaid = Boolean.FALSE;
	@Column(columnDefinition = "bit(1) default 0")
	private Boolean isHomeDeliveryAvailable = Boolean.FALSE;
	@Column(columnDefinition = "bit(1) default 0")
	private Boolean isFridgeAvailable = Boolean.FALSE;
	@Column
	private String latitude = "";
	@Column
	private String longitude = "";

	@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
	private List<PickupSchedule> pickupSchedules = new ArrayList<PickupSchedule>();	
	@ManyToMany(mappedBy = "locations", fetch = FetchType.LAZY)
	private List<Message> messages = new ArrayList<Message>();

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

	public String getDistrict() {
		return district;
	}

	public void setDistrict(String district) {
		this.district = district;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public String getPostCode() {
		return postCode;
	}

	public void setPostCode(String postCode) {
		this.postCode = postCode;
	}

	public String getContactPerson() {
		return contactPerson;
	}

	public void setContactPerson(String contactPerson) {
		this.contactPerson = contactPerson;
	}

	public String getTelephone() {
		return telephone;
	}

	public void setTelephone(String telephone) {
		this.telephone = telephone;
	}

	public String getMobilePhone() {
		return mobilePhone;
	}

	public void setMobilePhone(String mobilePhone) {
		this.mobilePhone = mobilePhone;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public TYPE getType() {
		return type;
	}

	public void setType(TYPE type) {
		this.type = type;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}
	
	

	public Boolean getIsCanceled() {
		return isCanceled;
	}

	public void setIsCanceled(Boolean isCanceled) {
		this.isCanceled = isCanceled;
	}

	public Boolean getIsPrepaid() {
		return isPrepaid;
	}

	public void setIsPrepaid(Boolean isPrepaid) {
		this.isPrepaid = isPrepaid;
	}


	public Boolean getIsHomeDeliveryAvailable() {
		return isHomeDeliveryAvailable;
	}

	public void setIsHomeDeliveryAvailable(Boolean isHomeDeliveryAvailable) {
		this.isHomeDeliveryAvailable = isHomeDeliveryAvailable;
	}	

	public Boolean getIsFridgeAvailable() {
		return isFridgeAvailable;
	}

	public void setIsFridgeAvailable(Boolean isFridgeAvailable) {
		this.isFridgeAvailable = isFridgeAvailable;
	}

	public String getLatitude() {
		return latitude;
	}

	public void setLatitude(String latitude) {
		this.latitude = latitude;
	}

	public String getLongitude() {
		return longitude;
	}

	public void setLongitude(String longitude) {
		this.longitude = longitude;
	}

	public List<PickupSchedule> getPickupSchedules() {
		return pickupSchedules;
	}

	public void setPickupSchedules(List<PickupSchedule> pickupSchedules) {
		this.pickupSchedules = pickupSchedules;
	}
	
	public List<Message> getMessages() {
		return messages;
	}

	public void setMessages(List<Message> messages) {
		this.messages = messages;
	}

	@Override
	public String toString() {
		return "Location [id=" + id + ", name=" + name + ", district="
				+ district + ", address=" + address + ", contactPerson="
				+ contactPerson + ", telephone=" + telephone + ", mobilePhone="
				+ mobilePhone + ", type=" + type + "]";
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((address == null) ? 0 : address.hashCode());
		result = prime * result
				+ ((contactPerson == null) ? 0 : contactPerson.hashCode());
		result = prime * result
				+ ((district == null) ? 0 : district.hashCode());
		result = prime * result
				+ ((mobilePhone == null) ? 0 : mobilePhone.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		result = prime * result
				+ ((telephone == null) ? 0 : telephone.hashCode());
		result = prime * result + ((type == null) ? 0 : type.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Location other = (Location) obj;
		if (address == null) {
			if (other.address != null)
				return false;
		} else if (!address.equals(other.address))
			return false;
		if (contactPerson == null) {
			if (other.contactPerson != null)
				return false;
		} else if (!contactPerson.equals(other.contactPerson))
			return false;
		if (district == null) {
			if (other.district != null)
				return false;
		} else if (!district.equals(other.district))
			return false;
		if (mobilePhone == null) {
			if (other.mobilePhone != null)
				return false;
		} else if (!mobilePhone.equals(other.mobilePhone))
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		if (telephone == null) {
			if (other.telephone != null)
				return false;
		} else if (!telephone.equals(other.telephone))
			return false;
		if (type == null) {
			if (other.type != null)
				return false;
		} else if (!type.equals(other.type))
			return false;
		return true;
	}

}
